package com.hyt.it.ogt.ykcj.service.exam.impl;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hyt.it.ogt.ykcj.common.enums.CommonEnums;
import com.hyt.it.ogt.ykcj.common.enums.ExamFormEnums;
import com.hyt.it.ogt.ykcj.common.utils.StringUtils;
import com.hyt.it.ogt.ykcj.domain.exam.EnterpriseExamScoreLineSetting;
import com.hyt.it.ogt.ykcj.domain.exam.EnterpriseExamScoreLineSettingSub;
import com.hyt.it.ogt.ykcj.domain.exam.ExamInfo;
import com.hyt.it.ogt.ykcj.domain.vo.*;
import com.hyt.it.ogt.ykcj.mapper.exam.EnterpriseExamScoreLineSettingMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.EnterpriseExamScoreLineSettingSubMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.EnterpriseExamineeSubjectGradeMapper;
import com.hyt.it.ogt.ykcj.service.exam.IExamInfoExternalService;
import com.hyt.it.ogt.ykcj.service.exam.IExamInfoService;
import com.hyt.it.ogt.ykcj.service.exam.IExamSubjectInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IEnterpriseExamineeSubjectGradeService;
import com.hyt.loginfo.service.IBaseLoginService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.collections4.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 考试信息Service业务层处理
 * 
 * @author admin
 * @date 2021-06-18
 */
@Service
public class ExamInfoExternalServiceImpl implements IExamInfoExternalService
{
	private static final Logger log = LoggerFactory.getLogger(ExamInfoExternalServiceImpl.class);

	@Autowired
	private EnterpriseExamScoreLineSettingMapper enterpriseExamScoreLineSettingMapper;

	@Autowired
	private EnterpriseExamScoreLineSettingSubMapper enterpriseExamScoreLineSettingSubMapper;

	@Autowired
	private EnterpriseExamineeSubjectGradeMapper enterpriseExamineeSubjectGradeMapper;

	@Autowired
	private IExamInfoService examInfoService;


	@Autowired
	private IBaseLoginService iBaseLoginService;

	@Autowired
	private IExamSubjectInfoService examSubjectInfoService;


	@Autowired
	private IEnterpriseExamineeSubjectGradeService enterpriseExamineeSubjectGradeService;

	@Autowired
	private ExamInfoMapper examInfoMapper;


	@Override
	public PageInfo<List<ExamInfoExternalVo>> getExamInfoExternalVos(QueryExamInfoVo queryExamInfoVo)  {
		PageHelper.startPage(queryExamInfoVo.getPageNum(), queryExamInfoVo.getPageSize());
		List<ExamInfoExternalVo> examInfoExternalVos  = examInfoService.getExamInfoExternalVosByOfficeId(iBaseLoginService.getOfficeId()
				,queryExamInfoVo.getBindingStatus(),queryExamInfoVo.getExamName());
		if(CollectionUtils.isEmpty(examInfoExternalVos)){
            return new PageInfo(Collections.EMPTY_LIST);
        }

		List<String> examIds = examInfoExternalVos.stream().distinct().map(e->e.getExamId()).collect(Collectors.toList());

		// 保存考试组关系---修改
		Map<String, List<String>> groupExamMap = new HashedMap<>();
		List<ExamInfo> examInfos = examInfoMapper.selectExamInfoByIds(examIds.stream().toArray(String[]::new));
		List<ExamInfo> groupExam = examInfos.stream().filter(item -> ExamFormEnums.FORM_EXAM_GROUP.getCode().equals(item.getExamForm())
				&& CommonEnums.EXAM_MERGE_TYPE_0.getCode().equals(String.valueOf(item.getMergeType()))).collect(Collectors.toList());
		for(ExamInfo examInfo : groupExam){
			ExamInfo queryParam = new ExamInfo();
			queryParam.setRelationId(examInfo.getId());
			List<ExamInfo> examInfoChild = examInfoMapper.selectExamInfoList(queryParam);
			if(CollectionUtils.isNotEmpty(examInfoChild)) {
				List<String> childExamIds = examInfoChild.stream().map(item -> item.getId()).collect(Collectors.toList());
				groupExamMap.put(examInfo.getId(), childExamIds);
				examIds.addAll(childExamIds);
			}
		}


		List<ExamScoreVo> maxExamScoreVos = enterpriseExamineeSubjectGradeService.getExamineeMaxScore(examIds);
        List<ExamScoreVo> minExamScoreVos = enterpriseExamineeSubjectGradeService.getExamineeMinScore(examIds);
        List<ExamSubjectVo>  examSubjectVos = examSubjectInfoService.selectExamSubjectListByExamIds(examIds);

        Map<String, BigDecimal> maxExamMap = maxExamScoreVos.stream().collect(Collectors.toMap(ExamScoreVo::getExamId, ExamScoreVo::getTotalScore, (k1, k2) -> k2));
        Map<String, BigDecimal> minExamMap = minExamScoreVos.stream().collect(Collectors.toMap(ExamScoreVo::getExamId, ExamScoreVo::getTotalScore, (k1, k2) -> k2));
        Map<String,  List<ExamSubjectVo>> examSubjectMap = examSubjectVos.stream().collect(Collectors.groupingBy(c -> c.getExamInfoId() ));

		// 保存考试组关系，给考试组赋值---修改
		groupExamMap.forEach((examId, childIdList) ->{
			List<ExamSubjectVo> subjectList = new ArrayList<>();
			for(String id : childIdList){
				if(CollectionUtils.isNotEmpty(examSubjectMap.get(id))){
					subjectList.addAll(examSubjectMap.get(id));
				}
			}
			if(CollectionUtils.isNotEmpty(subjectList)){
				examSubjectMap.put(examId,subjectList);
			}

			List<EnterpriseExamineeExamGradeVo> enterpriseExamineeSubjectGradeVos = enterpriseExamineeSubjectGradeMapper.selectSubjectEnterpriseExamineeByExamIds(childIdList.stream().toArray(String[]::new));
			// 子考试总成绩

			Map<String, BigDecimal> gradeMap = enterpriseExamineeSubjectGradeVos.stream().collect(Collectors.groupingBy(item->item.getIdCard()==null?"":item.getIdCard()+item.getName()==null?"":item.getName(),
					Collectors.reducing(BigDecimal.ZERO, EnterpriseExamineeExamGradeVo::getScore, BigDecimal::add)));
			List<BigDecimal> scoreList = new ArrayList<>();
			gradeMap.forEach((k,v) ->{
				scoreList.add(v);
			});
			BigDecimal maxScore = scoreList.stream().max((x1, x2) -> x1.compareTo(x2)).get();
			BigDecimal minScore = scoreList.stream().min((x1, x2) -> x1.compareTo(x2)).get();
			maxExamMap.put(examId, maxScore);
			minExamMap.put(examId, minScore);
		});


        for (ExamInfoExternalVo examInfoExternalVo : examInfoExternalVos){
			examInfoExternalVo.setMaxScore(maxExamMap.get(examInfoExternalVo.getExamId()));
			examInfoExternalVo.setMinScore(minExamMap.get(examInfoExternalVo.getExamId()));
			if(null != examInfoExternalVo.getMaxScore() && null != examInfoExternalVo.getMinScore()){
				examInfoExternalVo.setAverageScore(examInfoExternalVo.getMaxScore().add(examInfoExternalVo.getMinScore()).divide(new BigDecimal(2)));
			}else if(null != examInfoExternalVo.getMaxScore()){
				examInfoExternalVo.setAverageScore(examInfoExternalVo.getMaxScore());
			}else if(null != examInfoExternalVo.getMinScore()){
				examInfoExternalVo.setAverageScore(examInfoExternalVo.getMinScore());
			}
			if(CollectionUtils.isEmpty(examSubjectMap.get(examInfoExternalVo.getExamId()))){
				continue;
			}
			BigDecimal totalScore = examSubjectMap.get(examInfoExternalVo.getExamId()).stream().filter(e -> null != e.getPaperFullMarks()).map(ExamSubjectVo::getPaperFullMarks).reduce(BigDecimal.ZERO, BigDecimal::add);
			examInfoExternalVo.setTotalScore(totalScore);

		}
		return new PageInfo(examInfoExternalVos);
	}

	@Override
	public List<ExamInfoExternalVo> getExamInfoExternalDetail(List<String> examIds) {

		// 保存考试组关系---修改
		Map<String, List<String>> groupExamMap = new HashedMap<>();
		List<ExamInfo> examInfos = examInfoMapper.selectExamInfoByIds(examIds.stream().toArray(String[]::new));
		List<ExamInfo> groupExam = examInfos.stream().filter(item -> ExamFormEnums.FORM_EXAM_GROUP.getCode().equals(item.getExamForm())
				&& CommonEnums.EXAM_MERGE_TYPE_0.getCode().equals(String.valueOf(item.getMergeType()))).collect(Collectors.toList());
		for(ExamInfo examInfo : groupExam){
			ExamInfo queryParam = new ExamInfo();
			queryParam.setRelationId(examInfo.getId());
			List<ExamInfo> examInfoChild = examInfoMapper.selectExamInfoList(queryParam);
			if(CollectionUtils.isNotEmpty(examInfoChild)) {
				List<String> childExamIds = examInfoChild.stream().map(item -> item.getId()).collect(Collectors.toList());
				groupExamMap.put(examInfo.getId(), childExamIds);
				examIds.addAll(childExamIds);
			}
		}


		List<ExamInfoExternalVo> examInfoExternalVos  = examInfoService.getExamInfoExternalVosByExamIds(examIds);
		if(CollectionUtils.isEmpty(examInfoExternalVos)){
			return null;
		}
         List<ExamScoreVo> maxExamScoreVos = enterpriseExamineeSubjectGradeService.getExamineeMaxScore(examIds);
        List<ExamScoreVo> minExamScoreVos = enterpriseExamineeSubjectGradeService.getExamineeMinScore(examIds);
        List<ExamSubjectVo>  examSubjectVos = examSubjectInfoService.selectExamSubjectListByExamIds(examIds);

        Map<String, BigDecimal> maxExamMap = maxExamScoreVos.stream().collect(Collectors.toMap(ExamScoreVo::getExamId, ExamScoreVo::getTotalScore, (k1, k2) -> k2));
        Map<String, BigDecimal> minExamMap = minExamScoreVos.stream().collect(Collectors.toMap(ExamScoreVo::getExamId, ExamScoreVo::getTotalScore, (k1, k2) -> k2));
        Map<String,  List<ExamSubjectVo>> examSubjectMap = examSubjectVos.stream().collect(Collectors.groupingBy(c -> c.getExamInfoId() ));


		// 保存考试组关系，给考试组赋值---修改
		groupExamMap.forEach((examId, childIdList) ->{
			List<ExamSubjectVo> subjectList = new ArrayList<>();
			for(String id : childIdList){
				if(CollectionUtils.isNotEmpty(examSubjectMap.get(id))){
					subjectList.addAll(examSubjectMap.get(id));
				}
			}
			if(CollectionUtils.isNotEmpty(subjectList)){
				examSubjectMap.put(examId,subjectList);
			}

			List<EnterpriseExamineeExamGradeVo> enterpriseExamineeSubjectGradeVos = enterpriseExamineeSubjectGradeMapper.selectSubjectEnterpriseExamineeByExamIds(childIdList.stream().toArray(String[]::new));
			// 子考试总成绩

			Map<String, BigDecimal> gradeMap = enterpriseExamineeSubjectGradeVos.stream().collect(Collectors.groupingBy(item->item.getIdCard()==null?"":item.getIdCard()+item.getName()==null?"":item.getName(),
					Collectors.reducing(BigDecimal.ZERO, EnterpriseExamineeExamGradeVo::getScore, BigDecimal::add)));
			List<BigDecimal> scoreList = new ArrayList<>();
			gradeMap.forEach((k,v) ->{
				scoreList.add(v);
			});
			BigDecimal maxScore = scoreList.stream().max((x1, x2) -> x1.compareTo(x2)).get();
			BigDecimal minScore = scoreList.stream().min((x1, x2) -> x1.compareTo(x2)).get();
			maxExamMap.put(examId, maxScore);
			minExamMap.put(examId, minScore);
		});

        for (ExamInfoExternalVo examInfoExternalVo : examInfoExternalVos){
			examInfoExternalVo.setMaxScore(maxExamMap.get(examInfoExternalVo.getExamId()));
			examInfoExternalVo.setMinScore(minExamMap.get(examInfoExternalVo.getExamId()));
			if(null != examInfoExternalVo.getMaxScore() && null != examInfoExternalVo.getMinScore()){
				examInfoExternalVo.setAverageScore(examInfoExternalVo.getMaxScore().add(examInfoExternalVo.getMinScore()).divide(new BigDecimal(2)));
			}else if(null != examInfoExternalVo.getMaxScore()){
				examInfoExternalVo.setAverageScore(examInfoExternalVo.getMaxScore());
			}else if(null != examInfoExternalVo.getMinScore()){
				examInfoExternalVo.setAverageScore(examInfoExternalVo.getMinScore());
			}

			if(CollectionUtils.isEmpty(examSubjectMap.get(examInfoExternalVo.getExamId()))){
				continue;
			}

			BigDecimal totalScore = examSubjectMap.get(examInfoExternalVo.getExamId()).stream().filter(e -> null != e.getPaperFullMarks()).map(ExamSubjectVo::getPaperFullMarks).reduce(BigDecimal.ZERO, BigDecimal::add);
			examInfoExternalVo.setTotalScore(totalScore);
			Map<String,String> examSubjectNameMap = examSubjectVos.stream().filter(e->StringUtils.isNotEmpty(e.getSubjectName())).collect(Collectors.toMap(ExamSubjectVo::getSubjectId, ExamSubjectVo::getSubjectName, (k1, k2) -> k2));
			examInfoExternalVo.setExamScoreLineVos(getExamScoreLineVos(  examInfoExternalVo.getExamId() ,  CommonEnums.SCORE_LINE_DIMENSION_0.getCode(), examSubjectNameMap));

		}

        // 保存考试组关系，给考试组赋值, 去除子考试---修改
		for(ExamInfo examInfo : examInfos){
			if(ExamFormEnums.FORM_EXAM_GROUP.getCode().equals(examInfo.getExamForm())
					&& CommonEnums.EXAM_MERGE_TYPE_0.getCode().equals(String.valueOf(examInfo.getMergeType()))){
				List<String> strings = groupExamMap.get(examInfo.getId());
				Iterator<ExamInfoExternalVo> iterator = examInfoExternalVos.iterator();
				while (iterator.hasNext()){
					ExamInfoExternalVo next = iterator.next();
					if(strings.contains(next.getExamId())){
						iterator.remove();
					}
				}
			}
		}



		return  examInfoExternalVos;
	}




	private  List<ExamScoreLineVo> getExamScoreLineVos(String examId ,String dimension,Map<String,String> examSubjectNameMap){
		List<ExamScoreLineVo> examScoreLineVos = new ArrayList<>();
		EnterpriseExamScoreLineSetting enterpriseExamScoreLineSetting = new EnterpriseExamScoreLineSetting();
		enterpriseExamScoreLineSetting.setExamId(examId);
		enterpriseExamScoreLineSetting.setDimension(dimension);
		List<EnterpriseExamScoreLineSetting> examPostScoreLineSettings = enterpriseExamScoreLineSettingMapper.selectEnterpriseExamScoreLineSettingList(enterpriseExamScoreLineSetting);
		if (CollectionUtils.isEmpty(examPostScoreLineSettings)) {
			return  examScoreLineVos;
		}
		for (EnterpriseExamScoreLineSetting scoreLineSetting : examPostScoreLineSettings) {
			EnterpriseExamScoreLineSettingSub enterpriseExamScoreLineSettingSub = new EnterpriseExamScoreLineSettingSub();
			enterpriseExamScoreLineSettingSub.setEnterpriseExamScoreLineSettingId(scoreLineSetting.getId());
			List<EnterpriseExamScoreLineSettingSub> examPostScoreLineSettingSubs = enterpriseExamScoreLineSettingSubMapper
					.selectEnterpriseExamScoreLineSettingSubList(enterpriseExamScoreLineSettingSub);
			if (CollectionUtils.isEmpty(examPostScoreLineSettingSubs)) {
				continue;
			}
			//单科
			if(CommonEnums.SCORE_LINE_TYPE_0.getCode().equals(scoreLineSetting.getComposite())){
				for (EnterpriseExamScoreLineSettingSub scoreLineSettingSub :examPostScoreLineSettingSubs) {
					String comparisonTypeDesc = "";
					if(CommonEnums.COMPARISON_TYPE_1.getCode().equals(scoreLineSettingSub.getComparisonType())){
						comparisonTypeDesc =CommonEnums.COMPARISON_TYPE_1.getDesc();
					}else  if(CommonEnums.COMPARISON_TYPE_0.getCode().equals(scoreLineSettingSub.getComparisonType())){
						comparisonTypeDesc =CommonEnums.COMPARISON_TYPE_0.getDesc();
					}
					ExamScoreLineVo examScoreLineVo = new ExamScoreLineVo();
					examScoreLineVo.setScoreLine(null == scoreLineSettingSub.getScore() ? null : scoreLineSettingSub.getScore().toString());
					examScoreLineVo.setScoreLineType(comparisonTypeDesc);
					if(MapUtils.isNotEmpty(examSubjectNameMap)){
                        examScoreLineVo.setScoreSubjectName(examSubjectNameMap.get(scoreLineSettingSub.getSubjectId()));
                    }

					examScoreLineVos.add(examScoreLineVo);
				}
				//复合
			}else if(CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(scoreLineSetting.getComposite())){
				String comparisonTypeDesc = "";
				List<String> subjectNames = new ArrayList<>();
				//复合设置存储数据都是一样的分数和类型
				for (EnterpriseExamScoreLineSettingSub scoreLineSettingSub :examPostScoreLineSettingSubs) {
                    if(MapUtils.isNotEmpty(examSubjectNameMap)){
                        subjectNames.add(examSubjectNameMap.get(scoreLineSettingSub.getSubjectId()));
                    }
				}
				if(CommonEnums.COMPARISON_TYPE_1.getCode().equals(examPostScoreLineSettingSubs.get(0).getComparisonType())){
					comparisonTypeDesc =CommonEnums.COMPARISON_TYPE_1.getDesc();
				}else  if(CommonEnums.COMPARISON_TYPE_0.getCode().equals(examPostScoreLineSettingSubs.get(0).getComparisonType())){
					comparisonTypeDesc =CommonEnums.COMPARISON_TYPE_0.getDesc();
				}
				ExamScoreLineVo examScoreLineVo = new ExamScoreLineVo();
				examScoreLineVo.setScoreLine(null == examPostScoreLineSettingSubs.get(0).getScore() ? null : examPostScoreLineSettingSubs.get(0).getScore().toString());
				examScoreLineVo.setScoreLineType(comparisonTypeDesc);
				examScoreLineVo.setScoreSubjectName(StringUtils.join(subjectNames,"/"));
				examScoreLineVos.add(examScoreLineVo);

				//区间
			}else if(CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(scoreLineSetting.getComposite())){
				for (EnterpriseExamScoreLineSettingSub scoreLineSettingSub :examPostScoreLineSettingSubs) {
					ExamScoreLineVo examScoreLineVo = new ExamScoreLineVo();
					if(null != scoreLineSettingSub.getRegionStartScore() && null != scoreLineSettingSub.getRegionEndScore()){
						examScoreLineVo.setScoreLine(scoreLineSettingSub.getRegionStartScore()+"-"+scoreLineSettingSub.getRegionEndScore());
					}
					examScoreLineVo.setScoreLineType(scoreLineSettingSub.getRegionName());
					examScoreLineVo.setScoreSubjectName(examSubjectNameMap.get(scoreLineSettingSub.getSubjectId()));
					examScoreLineVos.add(examScoreLineVo);
				}
			}

		}
		return  examScoreLineVos;

	}
}